package com.uinnova.product.eam.service.asset.impl;

import cn.hutool.json.JSONArray;
import com.binary.core.exception.BinaryException;
import com.binary.core.util.BinaryUtils;
import com.uinnova.product.eam.base.util.EamUtil;
import com.uinnova.product.eam.comm.dto.ConfigListDto;
import com.uinnova.product.eam.comm.model.AppSystemQueryConParam;
import com.uinnova.product.eam.comm.model.es.EamAppConfig;
import com.uinnova.product.eam.model.dto.EamAppConfigDto;
import com.uinnova.product.eam.model.vo.EamAppConfigVo;
import com.uinnova.product.eam.service.asset.AppConfigSvc;
import com.uinnova.product.eam.service.es.EamConfigDao;
import com.uinnova.product.eam.service.es.IamsESCIDesignSvc;
import com.uino.bean.cmdb.base.ESCIAttrDefInfo;
import com.uino.bean.cmdb.base.ESCIClassInfo;
import com.uino.bean.cmdb.base.ESCIInfo;
import com.uino.bean.sys.base.ESDictionaryItemInfo;
import com.uino.bean.sys.query.ESDictionaryItemSearchBean;
import com.uino.dao.cmdb.CiClassProDropSourceDefHelper;
import com.uino.dao.cmdb.ESCIClassSvc;
import com.uino.service.sys.microservice.impl.DictionarySvc;
import com.uino.util.sys.SysUtil;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class AppConfigSvcImpl implements AppConfigSvc {

    @Autowired
    private EamConfigDao eamConfigDao;

    @Resource
    private ESCIClassSvc classSvc;

    @Resource
    private IamsESCIDesignSvc iamsESCIDesignSvc;

    @Resource
    DictionarySvc dictionarySvc;

    @Override
    public Long saveFilterConfig(EamAppConfigDto appSysConfig) {
        BoolQueryBuilder query = new  BoolQueryBuilder();
        query.must(QueryBuilders.termQuery("cardId",appSysConfig.getCardId()))
                        .must(QueryBuilders.termQuery("classCode.keyword",appSysConfig.getClassCode()));
        List<EamAppConfig> listByQuery = eamConfigDao.getListByQuery(query);
        if(!BinaryUtils.isEmpty(listByQuery) && BinaryUtils.isEmpty(appSysConfig.getId())){
            throw new BinaryException("配置数据已存在，请勿重复保存");
        }
        BinaryUtils.checkEmpty(appSysConfig.getCardId(), "卡片id不能为空，请检查");
        BinaryUtils.checkEmpty(appSysConfig.getClassCode(), "分类classCode不能为空，请检查");
        EamAppConfig config = EamUtil.copy(appSysConfig, EamAppConfig.class);
        return eamConfigDao.saveOrUpdate(config);
    }

    @Override
    public EamAppConfigVo queryFilterConfig(String classCode,Long cardId) {
        BinaryUtils.checkEmpty(classCode, "分类classCode不存在，请检查");
        BoolQueryBuilder queryParam = new BoolQueryBuilder();
        queryParam.must(QueryBuilders.termQuery("cardId",cardId))
                        .must(QueryBuilders.termQuery("classCode.keyword",classCode));
        EamAppConfig config = eamConfigDao.selectOne(queryParam);
        if(BinaryUtils.isEmpty(config)){
            return null;
        }
        EamAppConfigVo configVo = EamUtil.copy(config, EamAppConfigVo.class);
        BoolQueryBuilder query = new BoolQueryBuilder();
        query.must(QueryBuilders.termQuery("classCode.keyword", classCode));
        List<ESCIClassInfo> classInfoList = classSvc.getListByQuery(query);
        if (BinaryUtils.isEmpty(classInfoList)) {
            throw new BinaryException("分类信息不存在,分类标识：" + classCode);
        }

        List<ESCIAttrDefInfo> attrDefs = classInfoList.get(0).getAttrDefs();
        //保存的属性选项
        List<ESCIAttrDefInfo> newAttrDefs = new ArrayList<>();
        //key = proName;value = 属性信息
        Map<Long, ESCIAttrDefInfo> defIdMap = attrDefs.stream().collect(Collectors.toMap(ESCIAttrDefInfo::getId, each -> each, (k1, k2) -> k1));
        Map<String, ESCIAttrDefInfo> proNameMap = attrDefs.stream().collect(Collectors.toMap(ESCIAttrDefInfo::getProName, each -> each, (k1, k2) -> k1));
        //刷新存量数据
        if(!BinaryUtils.isEmpty(config.getAttrList()) && BinaryUtils.isEmpty(config.getAttrIds())){
            List<Long> defIdList = new ArrayList<>();
            for (String proName : config.getAttrList()) {
                ESCIAttrDefInfo defInfo = proNameMap.get(proName);
                defIdList.add(defInfo.getId());
            }
            config.setAttrIds(defIdList);
        }
        if(BinaryUtils.isEmpty( config.getAttrIds())){
            return configVo;
        }
        for (Long defId : config.getAttrIds()) {
            if(!BinaryUtils.isEmpty(defIdMap.get(defId))){
                newAttrDefs.add(defIdMap.get(defId));
            }
        }
        //排个序，按照对象定义的属性顺序返回展示；
//        List<String> attrDefNames = attrDefs.stream().map(ESCIAttrDefInfo::getProName).collect(Collectors.toList());
//        newAttrDefs.sort(Comparator.comparing(each -> attrDefNames.indexOf(each.getProName())));
        List<ConfigListDto> configLists = new ArrayList<>();
        //给数据字典用
        List<Long> dictIds = newAttrDefs.stream().filter(each -> each.getProType() == 8)
                .filter(each -> !BinaryUtils.isEmpty(each.getProDropSourceDef()))
                .map(each -> CiClassProDropSourceDefHelper.getCiClassProDropSourceClassId(each.getProDropSourceDef().trim())).collect(Collectors.toList());
        Map<Long, List<ESDictionaryItemInfo>> dictItemMap = new HashMap<>();
        if (!BinaryUtils.isEmpty(dictIds)) {
            ESDictionaryItemSearchBean bean = new ESDictionaryItemSearchBean();
            bean.setDictClassIds(dictIds.toArray(new Long[]{}));
            List<ESDictionaryItemInfo> dictItemByIds = dictionarySvc.searchDictItemListByBean(bean);
            if (!BinaryUtils.isEmpty(dictItemByIds)) {
                dictItemMap = dictItemByIds.stream().collect(Collectors.groupingBy(ESDictionaryItemInfo::getDictClassId));
            }
        }
        //给关联属性用
        List<Long> classIds = newAttrDefs.stream().filter(each -> each.getProType() == 11)
                .filter(each -> !BinaryUtils.isEmpty(each.getProDropSourceDef()))
                .map(each -> CiClassProDropSourceDefHelper.getCiClassProDropSourceClassId(each.getProDropSourceDef())).collect(Collectors.toList());
        //取到分类id,查出对应设计库数据；
        Map<Long, String> defMap = null;
        List<ESCIInfo> designCiInfoList = null;
        if (!BinaryUtils.isEmpty(classIds)) {
            List<ESCIClassInfo> classList = classSvc.getAllDefESClassInfosByClassIds(SysUtil.getCurrentUserInfo().getDomainId(), classIds);
            if (!BinaryUtils.isEmpty(classList)) {
                defMap = classList.stream().map(ESCIClassInfo::getAttrDefs).flatMap(Collection::stream).collect(Collectors.toMap(ESCIAttrDefInfo::getId, ESCIAttrDefInfo::getProName));
            }
            BoolQueryBuilder boolQueryBuilder= new BoolQueryBuilder();
            boolQueryBuilder.must(QueryBuilders.termsQuery("classId", classIds));
            designCiInfoList = iamsESCIDesignSvc.getListByQuery(boolQueryBuilder);
        }
        for (ESCIAttrDefInfo attrDef : newAttrDefs) {
            ConfigListDto configDto = new ConfigListDto();
            configDto.setProType(attrDef.getProType());
            configDto.setTitle(attrDef.getProName());
            List<AppSystemQueryConParam> conditionList = new ArrayList<>();
            //字符串，文本，日期，同逻辑处理
            if (attrDef.getProType() == 3 || attrDef.getProType() == 4 || attrDef.getProType() == 7) {
                configDto.setConditions(conditionList);
            }
            //枚举
            if (attrDef.getProType() == 6 && !BinaryUtils.isEmpty(attrDef.getEnumValues())) {
                String enumValues = attrDef.getEnumValues();
                JSONArray jsonArray = new JSONArray(enumValues);
                for (Object json : jsonArray) {
                    //用构造方法是不是就直接set值了
                    AppSystemQueryConParam conParam = new AppSystemQueryConParam(json.toString(), null);
                    conditionList.add(conParam);
                }
                configDto.setConditions(conditionList);
            }
            //字典 对象定义中绑定的是某个字典表
            if (attrDef.getProType() == 8 && !BinaryUtils.isEmpty(attrDef.getProDropSourceDef()) && !BinaryUtils.isEmpty(dictItemMap)) {
                Long dictClassId = CiClassProDropSourceDefHelper.getCiClassProDropSourceClassId(attrDef.getProDropSourceDef().trim());
                List<ESDictionaryItemInfo> esDictionaryItemList = dictItemMap.get(dictClassId);
                if (!BinaryUtils.isEmpty(esDictionaryItemList)) {
                    for (ESDictionaryItemInfo itemInfo : esDictionaryItemList) {
                        String keyCode = itemInfo.getKeyCode();
                        Map<String, String> attrs = itemInfo.getAttrs();
                        //取到keyCode对应的属性名称；
                        AppSystemQueryConParam conParam = new AppSystemQueryConParam(keyCode, attrs.get("颜色"));
                        conditionList.add(conParam);
                    }
                    configDto.setConditions(conditionList);
                }
            }
            //关联属性 关联的是设计库的分类的属性 分类id:属性id,属性id
            if (attrDef.getProType() == 11 && !BinaryUtils.isEmpty(attrDef.getProDropSourceDef())) {
                Long classId = CiClassProDropSourceDefHelper.getCiClassProDropSourceClassId(attrDef.getProDropSourceDef().trim());
                Long[] attrDefIds = CiClassProDropSourceDefHelper.getCiClassProDropSourceDefIds(attrDef.getProDropSourceDef().trim());
                //属性名称
                if (!BinaryUtils.isEmpty(designCiInfoList) && !BinaryUtils.isEmpty(defMap)) {
                    for (ESCIInfo esciInfo : designCiInfoList) {
                        if (!esciInfo.getClassId().equals(classId)) {
                            continue;
                        }
                        List<String> attrValues = new ArrayList<>();
                        for (Long attrDefId : attrDefIds) {
                            String proName = defMap.get(attrDefId);
                            Object attrValue = esciInfo.getAttrs().get(proName);
                            if (!BinaryUtils.isEmpty(attrValue)) {
                                attrValues.add(attrValue.toString());
                            }
                        }
                        if (!BinaryUtils.isEmpty(attrValues)) {
                            AppSystemQueryConParam conParam = new AppSystemQueryConParam(
                                    String.join(CiClassProDropSourceDefHelper.DEF_PRONAME_SEPARATOR, attrValues), null);
                            conditionList.add(conParam);
                        }
                    }
                    configDto.setConditions(conditionList);
                }
            }
            configLists.add(configDto);
        }
        configVo.setConfigLists(configLists);
        return configVo;
    }


}
